#include <ring_buffer.h>
#include <egos_kernel.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

RingBuffer* RingBufferCreate(uint32 size, EgosTaskId reader, EgosTaskId writer)
{
	RingBuffer *q 	= malloc(sizeof(RingBuffer));
	q->writeIdx 	= 0;
	q->readIdx 		= size - 1;
	q->maxSize_1 	= size - 1;
	q->entries 		= malloc(size * sizeof(void*));
	q->reader 		= reader;
	q->writer 		= writer;

	memset(q->entries, INVALID_UINT8, size * sizeof(void*));

	return q;
}

bool RingBufferIsEmpty(RingBuffer *q)
{
	return ((1 + q->readIdx)&q->maxSize_1) == (q->writeIdx & q->maxSize_1);
}

bool RingBufferIsFull(RingBuffer *q)
{
	return (q->readIdx & q->maxSize_1) == (q->writeIdx & q->maxSize_1);
}

bool RingBufferWriteEntry(RingBuffer *q, void* entry)
{
	if(EgosGetCurrentTaskID() != q->writer)
	{
		WARN("wrong writer task");
		return FALSE;
	}
	if(!RingBufferIsFull(q))
	{
		q->entries[(q->writeIdx & q->maxSize_1)] = entry;
		q->writeIdx++;
		return TRUE;
	}
	WARN("Buffer Full!!");
	return FALSE;
}

bool RingBufferReadEntry(RingBuffer *q, void **entry)
{
	if(EgosGetCurrentTaskID() != q->reader)
	{
		WARN("wrong reader task");
		return FALSE;
	}
	if(!RingBufferIsEmpty(q))
	{
		q->readIdx++;
		*entry = q->entries[(q->readIdx & q->maxSize_1)];
		q->entries[(q->readIdx & q->maxSize_1)] = (void*)INVALID_UINT32;
		return TRUE;
	}
	WARN("Buffer Empty!!");
	return FALSE;
}

void RingBufferDump(RingBuffer *q)
{
	int i;
	PRINT2N("read index = %d, write index = %d", q->readIdx, q->writeIdx);
	for(i = 0; i <= q->maxSize_1; i++)
		PRINT2N("entry %d = 0x%08x", i, (uint32)q->entries[i]);
}
